let currentTransport, currentDataChannel = null
let onCloseCb = [], onCb = new Map()

function log(...data) {
    console.log(data)
}

function OnClose(f) {
    onCloseCb = onCloseCb.concat(f)
}

function On(header, f) {
    let cbs = []
    if (onCb.has(header)) {
        cbs = onCb.get(header)
    }
    cbs = cbs.concat(f)
    onCb.set(header, cbs)
}

function fireOnClose(...data) {
    for (let f of onCloseCb) {
        f(data)
    }
}

function fireOn(header, body) {
    if (onCb.has(header)) {
        for (let f of onCb.get(header)) {
            f(header, body)
        }
    }
    if (onCb.has("*")) {
        for (let f of onCb.get("*")) {
            f(header, body)
        }
    }

}

// 连接服务器
async function Connect(url) {
    try {
        currentTransport = new RTCPeerConnection({
            iceServers: [
            ]
        })

        currentDataChannel = currentTransport.createDataChannel("signal")
        let offer = await currentTransport.createOffer()
        currentDataChannel.onmessage = (e) => {
            let buf = new Uint8Array(e.data)
            if (buf.length > 8) {
                // 读取长度信息
                let lenHeader = bytesToInt(buf.slice(0, 4))
                let lenBody = bytesToInt(buf.slice(4, 8))
                buf = buf.slice(8)
                let header, body
                let decoder = new TextDecoder('utf-8')
                // 读取header
                header = decoder.decode(buf.slice(0, lenHeader))
                buf = buf.slice(lenHeader)
                // 读取body
                body = decoder.decode(buf.slice(0, lenBody))
                // 单次读取完毕
                fireOn(header, body)
            }
        }

        currentTransport.onconnectionstatechange=()=>{
            if ("disconnected"===currentTransport.connectionState){
                currentTransport = null
                currentDataChannel = null
                fireOnClose()
            }
        }

        currentTransport.onicegatheringstatechange = () => {
            if ("complete" === currentTransport.iceGatheringState) {

                let requestInstance = new Request(url, {
                    method: 'post',
                    body: btoa(JSON.stringify(currentTransport.localDescription))
                })

                fetch(requestInstance).then(response => {
                    let result = response.text()
                    result.then(res => {
                        currentTransport.setRemoteDescription(JSON.parse(atob(res)))
                    })
                }).catch(()=>{
                    currentTransport = null
                    currentDataChannel = null
                    fireOnClose()
                })
            }
        }

        await currentTransport.setLocalDescription(offer)

    } catch (e) {
        currentTransport = null
        currentDataChannel = null
        fireOnClose(e)
    }
}

async function Emit(header, body) {
    if (null != currentDataChannel) {
        let encoder = new TextEncoder("utf-8");
        try {
            header = encoder.encode(header)
            body = encoder.encode(body)
            let buf = new Uint8Array(0)
            buf = concat(buf, intToBytes(header.length))
            buf = concat(buf, intToBytes(body.length))
            buf = concat(buf, header)
            buf = concat(buf, body)
            currentDataChannel.send(buf)
        } catch (e) {
            log("发送数据异常", e)
        }
    }
}

function bytesToInt(raw) {
    return (raw[0] & 0xff) << 24 | (raw[1] & 0xff) << 16 | (raw[2] & 0xff) << 8 | (raw[3]) & 0xff
}

function intToBytes(raw) {
    let result = new Uint8Array(4)
    result[0] = (raw >> 24) & 0xff
    result[1] = (raw >> 16) & 0xff
    result[2] = (raw >> 8) & 0xff
    result[3] = raw & 0xff
    return result
}

function concat(a, b) {
    return Uint8Array.from(Array.from(a).concat(Array.from(b)))
}